﻿using IdentityServer4.Models;
using IdentityServer4.Services;
using IdentityServer4.Stores;
using MvcAuthSample.Models;
using System;
using System.Linq;
using System.Threading.Tasks;

namespace MvcAuthSample.Servers
{
    public class ConsentService
    {
        private readonly IIdentityServerInteractionService identiryserverInteractionService;
        private readonly IClientStore clientStore;
        private readonly IResourceStore resourceStore;
        public ConsentService(IIdentityServerInteractionService identiryserverInteractionService, IClientStore clientStore, IResourceStore resourceStore)
        {
            this.identiryserverInteractionService = identiryserverInteractionService;
            this.clientStore = clientStore;
            this.resourceStore = resourceStore;
        }
        public async Task<ProcessConsentResult> PorcessConsent(InputConsentViewModel model)
        {
            var result = new ProcessConsentResult();
            ConsentResponse consentResponse = null;
            if (model.Button == "no")
            {
                consentResponse = ConsentResponse.Denied;
            }
            else //if (viewModel.Button == "yes")
            {
                if (model.ScopesConented != null && model.ScopesConented.Any())
                {
                    consentResponse = new ConsentResponse
                    {
                        ScopesConsented = model.ScopesConented,
                        RememberConsent = model.RemeberConsent          //是否记住
                    };
                }
               else
                {
                    result.ValidationError = "请至少选中一个权限";
                }
            }
            if (consentResponse != null)
            {
                var request = await identiryserverInteractionService.GetAuthorizationContextAsync(model.ReturnUrl);
                await identiryserverInteractionService.GrantConsentAsync(request, consentResponse);

                result.RedirectUrl = model.ReturnUrl;
            }
            var consentViewModel = await BuidConsentViewModel(model.ReturnUrl, model);
            result.ConsentViewModel = consentViewModel;
            return result;
        }

        public async Task<ConsentViewModel> BuidConsentViewModel(string returnUrl, InputConsentViewModel model = null)
        {
            var request = await identiryserverInteractionService.GetAuthorizationContextAsync(returnUrl);
            if (request == null)
            {
                return null;
            }
            var client = await clientStore.FindEnabledClientByIdAsync(request.ClientId);
            var resources = await resourceStore.FindEnabledResourcesByScopeAsync(request.ScopesRequested);
            var vm = CreateConsentViewModel(request, client, resources, model);
            vm.ReturnUrl = returnUrl;
            return vm;
        }
        private ConsentViewModel CreateConsentViewModel(AuthorizationRequest request, Client client, Resources resources, InputConsentViewModel model
            )
        {
            //用户选中的Scopes
            var selectedScopes = model?.ScopesConented ?? Enumerable.Empty<string>();
            //客户端传入信息填充consentViewModel
            var vm = new ConsentViewModel
            {
                ClientName = client.ClientName,
                ClientLogoUrl = client.LogoUri,
                ClientUri = client.ClientUri,
                RemeberConsent = model?.RemeberConsent ?? true,
                IdentiryScopes = resources.IdentityResources.Select(t => CreateScopeViewModel(t, selectedScopes.Contains(t.Name) || model == null)),    //resources的IdentityResources需要转换成我们自己的ViewModel ; 假如用户存在用户选中的Scope的话check 就传递一个true
                ResourceScopes = resources.ApiResources.SelectMany(t => t.Scopes).Select(e => CreateScopeViewModel(scope: e, check: selectedScopes.Contains(e.Name) || model == null))
            };
            return vm;
        }
        private ScopeViewModel CreateScopeViewModel(IdentityResource identityResource, bool check)
        {
            return new ScopeViewModel
            {
                Name = identityResource.Name,
                Checked = check || identityResource.Required,
                DisplayName = identityResource.DisplayName,
                Description = identityResource.Description,
                Required = identityResource.Required,
                Emphasize = identityResource.Emphasize
            };
        }
        private ScopeViewModel CreateScopeViewModel(Scope scope, bool check)
        {
            return new ScopeViewModel
            {
                Name = scope.Name,
                Checked = check || scope.Required,
                DisplayName = scope.DisplayName,
                Description = scope.Description,
                Required = scope.Required,
                Emphasize = scope.Emphasize
            };
        }
    }
}
